package com.joysuch.wwyt.common.service.impl;

import com.google.common.collect.Maps;
import com.joysuch.wwyt.bp.entity.dto.BpInvestigateRecordItemDto;
import com.joysuch.wwyt.bp.service.BpInvestigateRecordService;
import com.joysuch.wwyt.common.constant.Constant;
import com.joysuch.wwyt.common.enums.WfProcessStatusEnum;
import com.joysuch.wwyt.config.RedisClient;
import com.joysuch.wwyt.core.entity.BaseConfig;
import com.joysuch.wwyt.core.enums.BaseConfigCodes;
import com.joysuch.wwyt.core.service.BaseConfigService;
import com.joysuch.wwyt.patrol.constant.ExceptProcessStatus;
import com.joysuch.wwyt.patrol.entity.dto.TaskRecordItemDto;
import com.joysuch.wwyt.patrol.service.PatrolRecordItemService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import static com.joysuch.wwyt.common.enums.WfProcessStatusEnum.FINISHED;
import static com.joysuch.wwyt.common.enums.WfProcessStatusEnum.TERMINATE;

@Slf4j
@Service
public class WfProcessStatusSync {

    @Autowired
    private RedisClient redisClient;
    @Autowired
    private BpInvestigateRecordService investigateRecordService;
    @Autowired
    private PatrolRecordItemService patrolRecordItemService;
    @Autowired
    private BaseConfigService baseConfigService;

    @Scheduled(initialDelay = 20000, fixedDelay = 60 * 1000)
    public void syncProcessStatus() {

        List<BpInvestigateRecordItemDto> itemList = investigateRecordService.findWfRecordItemList();
        Map<String, List<Long>> todayDataMap = Maps.newHashMap();
        Map<String, List<Long>> historyDataMap = Maps.newHashMap();
        List<String> removeKeys = new ArrayList<>();
        itemList.forEach(each -> {
            BaseConfig ipConfig = baseConfigService.findConfig(each.getTenentId(), each.getOrgCode(), BaseConfigCodes.RISK_HIDDEN_DANGER_PROCESS_KEY);
            if (ipConfig != null) {
                String procDefKey = ipConfig.getValue();
                String processInsStatusKey = String.format(BaseConfigCodes.WORKFLOW_PROCESS_INS_STATUS_KEY, procDefKey, each.getWfProcessInsId());
                String status = redisClient.get(processInsStatusKey);
                if (StringUtils.isNotBlank(status)) {
                    if (FINISHED.getCode().equals(status)) {
                        final String finishedName = FINISHED.getName();
                        each.setWfProcessStatus(finishedName);
                        if (Constant.COMMON_SWITCH_ON.equals(each.getHistoryFlag())) {
                            builderHistoryData(historyDataMap, each.getId(), finishedName);
                        }else {
                            builderTodayData(todayDataMap, each.getId(), finishedName);
                        }
                    } else if (TERMINATE.getCode().equals(status)) {
                        final String terminateName = TERMINATE.getName();
                        each.setWfProcessStatus(terminateName);
                        if (Constant.COMMON_SWITCH_ON.equals(each.getHistoryFlag())) {
                            builderHistoryData(historyDataMap, each.getId(), terminateName);
                        }else {
                            builderTodayData(todayDataMap, each.getId(), terminateName);
                        }
                    }
                    if (WfProcessStatusEnum.getAllStatus().contains(status)) {
                        removeKeys.add(processInsStatusKey);
                    }
                }
            }
        });
        todayDataMap.forEach((k, v) -> {
            investigateRecordService.updateWfRecordItemByIds(k, v);
            v.forEach(itemId -> investigateRecordService.changePlanInvalid(itemId, "syncProcessStatus"));
        });
        historyDataMap.forEach((k, v) -> {
            investigateRecordService.updateWfRecordItemHisByIds(k, v);
            v.forEach(itemId -> investigateRecordService.changePlanInvalid(itemId, "syncProcessStatus"));
        });
        removeKeys.forEach(each -> redisClient.removeKey(each));
    }

    private void builderTodayData(Map<String, List<Long>> dataMap, Long itemId, String statusName) {
        if (dataMap.get(statusName) != null) {
            List<Long> ids = dataMap.get(statusName);
            ids.add(itemId);
        } else {
            List<Long> ids = new ArrayList<>();
            ids.add(itemId);
            dataMap.put(statusName, ids);
        }
    }

    private void builderHistoryData(Map<String, List<Long>> historyDataMap, Long itemId, String statusName) {
        if (historyDataMap.get(statusName) != null) {
            List<Long> ids = historyDataMap.get(statusName);
            ids.add(itemId);
        } else {
            List<Long> ids = new ArrayList<>();
            ids.add(itemId);
            historyDataMap.put(statusName, ids);
        }
    }

    @Scheduled(initialDelay = 20000, fixedDelay = 5 * 1000)
    public void syncPatrolProcessStatus() {
        List<TaskRecordItemDto> itemList = patrolRecordItemService.findWfRecordItemList();
        List<String> removeKeys = new ArrayList<>();
        itemList.forEach(each -> {
            BaseConfig ipConfig = baseConfigService.findConfig(each.getTenentId(), each.getOrgCode(), BaseConfigCodes.RISK_HIDDEN_DANGER_PROCESS_KEY);
            if (ipConfig != null) {
                String procDefKey = ipConfig.getValue();
                String processInsStatusKey = String.format(BaseConfigCodes.WORKFLOW_PROCESS_INS_STATUS_KEY, procDefKey, each.getWfProcessInsId());
                String status = redisClient.get(processInsStatusKey);
                if (StringUtils.isNotBlank(status)) {
                    if (WfProcessStatusEnum.getAllStatus().contains(status)) {
                        String statusName = null;
                        if (FINISHED.getCode().equals(status)) {
                            statusName = FINISHED.getName();
                        } else if (TERMINATE.getCode().equals(status)) {
                            statusName = TERMINATE.getName();
                        }
                        patrolRecordItemService.updateWfRecordItemById(statusName, ExceptProcessStatus.PROCESSING_FINISH, each.getId());
                        removeKeys.add(processInsStatusKey);
                    }
                }
            }
        });
        removeKeys.forEach(each -> redisClient.removeKey(each));
    }

}
